/*********************************************************************************

********************************************************************************/
 

#include "spi_tx_rx.h"
 #include "regs.h"



#define SPI_BURST_SIZE	29			// Read/Write Burst Size (For spi_write_then_read)
void IINCHIP_WRITE( uint32_t addrbsb,  uint8_t data,int fd)
{

    struct spi_ioc_transfer xfer[2];
    unsigned char buf[2048], *bp;
    int len, status;

    memset(xfer, 0, sizeof xfer);
    memset(buf, 0, sizeof buf);
    len = sizeof buf;

   buf[0] = (addrbsb & 0x00FF0000)>>16;
   buf[1] = (addrbsb & 0x0000FF00)>> 8;
   buf[2] = (addrbsb & 0x000000F8) + 4;
   buf[3] =  data;

   xfer[0].tx_buf = (unsigned long)buf;
   xfer[0].len = 4;

   status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);

	if (status < 0) {
	perror("SPI_IOC_MESSAGE");
	return;
}   

}

uint8_t IINCHIP_READ(uint32_t addrbsb,int fd)
{
   uint8_t data = 0;
   struct spi_ioc_transfer xfer[2];
    unsigned char buf[2048], *bp;
    int len, status;

    memset(xfer, 0, sizeof xfer);
    memset(buf, 0, sizeof buf);
    len = sizeof buf;


      buf[0] = (addrbsb & 0x00FF0000)>>16;
      buf[1] = (addrbsb & 0x0000FF00)>> 8;
      buf[2] = (addrbsb & 0x000000F8) ;

	len = 3;
	xfer[0].tx_buf = (unsigned long)buf;
	xfer[0].len = 3;


	xfer[1].rx_buf = (unsigned long) buf;
	xfer[1].len = 3;

	status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
    if (status < 0) {
    perror("SPI_IOC_MESSAGE");
    return 0;
    }

    return buf[0];
}

uint16_t wiz_read_buf(int fd,uint32_t addrbsb, uint8_t* buf,uint16_t len)
{
   struct spi_ioc_transfer tr[2];
   memset(&tr, 0, sizeof tr);
   
   uint8_t addr[SPI_BURST_SIZE + 3];
  //  uint8_t rx[1024];
   uint16_t idx = 0;
   uint8_t i;
  	uint8_t l = len / SPI_BURST_SIZE;
	uint8_t r = len % SPI_BURST_SIZE;

    for(i = 0 ; i < l ; i++)
	{
		addr[0] = (addrbsb & 0x00FF0000) >> 16;
		addr[1] = (addrbsb & 0x0000FF00) >> 8;
		addr[2] = (addrbsb & 0x000000F8);

		
        tr[0].tx_buf = (unsigned long)addr;
        tr[0].len = 3;
		    tr[1].len = SPI_BURST_SIZE;
        tr[1].rx_buf = (unsigned long)(buf+(i * SPI_BURST_SIZE));
        int status = ioctl(fd, SPI_IOC_MESSAGE(2), tr);
        if (status < 0) 
        {
            perror("SPI_IOC_MESSAGE");
            printf("%s  %d",__func__,__LINE__);
            return 0;
        }
		addrbsb += (SPI_BURST_SIZE << 8);
	}
    if(r > 0)
	{
		addr[0] = (addrbsb & 0x00FF0000) >> 16;
		addr[1] = (addrbsb & 0x0000FF00) >> 8;
		addr[2] = (addrbsb & 0x000000F8);

        tr[0].tx_buf = (unsigned long)addr;
        tr[0].len = 3;
		    tr[1].len = r;
        tr[1].rx_buf = (unsigned long)(buf+(i * SPI_BURST_SIZE));
        int status = ioctl(fd, SPI_IOC_MESSAGE(2), tr);
        if (status < 0) 
        {
            perror("SPI_IOC_MESSAGE");
            printf("%s  %d",__func__,__LINE__);
            return 0;
        }
		
	}
    return len;
}

uint16_t wiz_write_buf(int fd,uint32_t addrbsb,uint8_t* buf,uint16_t len)
{
   uint8_t addr[SPI_BURST_SIZE + 3];
   struct spi_ioc_transfer tr;
   memset(&tr, 0, sizeof tr);
   uint16_t idx = 0;
   uint8_t i;
  	uint8_t l = len / SPI_BURST_SIZE;
	uint8_t r = len % SPI_BURST_SIZE;

    for(i = 0 ; i < l ; i++)
	{
		addr[0] = (addrbsb & 0x00FF0000) >> 16;
		addr[1] = (addrbsb & 0x0000FF00) >> 8;
		addr[2] = (addrbsb & 0x000000F8) + 4;

		memcpy(addr + 3, buf + (i * SPI_BURST_SIZE), SPI_BURST_SIZE);
        tr.tx_buf = (unsigned long)addr;
        tr.len = SPI_BURST_SIZE + 3;
        int status = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
        if (status < 0) 
        {
            perror("SPI_IOC_MESSAGE");
            printf("%s  %d",__func__,__LINE__);
            return 0;
        }
		addrbsb += (SPI_BURST_SIZE << 8);
	}
    if(r > 0)
	{
		addr[0] = (addrbsb & 0x00FF0000) >> 16;
		addr[1] = (addrbsb & 0x0000FF00) >> 8;
		addr[2] = (addrbsb & 0x000000F8) + 4;

		memcpy(addr + 3, buf + (i * SPI_BURST_SIZE), r);
        tr.tx_buf = (unsigned long)addr;
        tr.len =  r + 3;
        int status = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
        if (status < 0) 
        {
            perror("SPI_IOC_MESSAGE");
            printf("%s  %d",__func__,__LINE__);
            return 0;
        }
		
	}
    
   return len;  
}



static void pabort(const char *s)
{
	perror(s);
	abort();//从调用的地方跳出
}

void set_spidev(struct spidev_t *spidev,char * dev_name,uint8_t mode,uint8_t bits,int speed,int delay)
{
	spidev->device = dev_name;
	spidev->mode = mode;
    spidev->bits = bits;
    spidev->speed = speed;
    spidev->delay = delay;
}
void  spi_init(int fd, int mode,int bits,int speed)
{
	/*
	 * spi mode
	 */
	int ret = 0;
	ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
	if (ret == -1)
		pabort("can't set spi mode");

	ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
	if (ret == -1)
		pabort("can't get spi mode");

	/*
	 * bits per word
	 */
	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
	if (ret == -1)
		pabort("can't set bits per word");

	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
	if (ret == -1)
		pabort("can't get bits per word");

	/*
	 * max speed hz
	 */
	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	if (ret == -1)
		pabort("can't set max speed hz");

	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
	if (ret == -1)
		pabort("can't get max speed hz");
}

int open_spidev(struct spidev_t *spidev)
{
    int fd = open(spidev->device, O_RDWR);
	if (fd < 0)
		pabort("can't open device");
    return fd;
}